/*
 * Node.cpp
 *
 *  Created on: 02-Sep-2014
 *      Author: ali
 */

#include "Include.h"
#include "CHSelectionMessage.h"
extern STAT gStat;
Node::Node() :
		m_nID(-1), m_dResidualPower(0), m_cMyPos(0, 0), m_bIsActive(true), m_eNodeType(
				eNodeNone), m_nCHSelectionWinner(0)
{

}
Node::Node(int id, double pow, const Coordinate& pos, eNodeType nodeTyoe) :
		m_nID(id), m_dResidualPower(pow), m_cMyPos(pos), m_bIsActive(true), m_eNodeType(
				nodeTyoe), m_nCHSelectionWinner(0)
{

}
double Node::GetResidualPower()
{
	return m_dResidualPower;
}
int Node::GetID()
{
	return m_nID;
}
Coordinate Node::GetPos()
{
	return m_cMyPos;
}
bool Node::GetNodeStatus()
{
	bool bStat = false;
	if (false == m_bIsActive)
	{
		return bStat;
	}
	else if (m_dResidualPower < dActivityhreasholdPower)
	{
		return bStat;
	}
	return bStat = true;
}

void Node::UpdateNodeStatus()
{
	if (false == m_bIsActive)
	{
		return;
	}
	else if (m_dResidualPower < dActivityhreasholdPower)
	{
		m_bIsActive = false;
	}
}

bool Node::Recv(Message& msg)
{
	bool bStat = false;
	if (false == GetNodeStatus())
	{
		return bStat;
	}
	m_dResidualPower -= RxPowerCalc(msg.GetMessageLeninBits());
	UpdateNodeStatus();
	return bStat;
}
bool Node::RecvCHSelectionMsg()
{
	bool bStat = Channel::ReadMessageFromChannel(m_cCurMsg);
	bStat = Recv(m_cCurMsg);
	return bStat;
}

bool Node::SendCHSelectionMsg()
{

	double myResidualPower = m_dResidualPower - dPowerForLEACHAD;

	Message chSelectionMSG(eCHSelection, LEACH_AD_MESSAG, myResidualPower,
			m_nCHSelectionWinner);
	bool bStat = Send(chSelectionMSG, LEACH_AD_DISTANCE);

	return bStat;
}
bool Node::Send(Node &target)
{
	bool bStat;
	double distance = (target.GetPos()).GetDistance(GetPos());

#if 0
	if((GetNodeType() == eCHSensor )&&(m_eNodeType == target.GetNodeType() ))
	{
		bStat = SendCHtoCH(m_cDataMsg, distance); // tx power
	}
	else
	{
		bStat = Send(m_cDataMsg, distance); // tx power
	}
#else
	bStat = Send(m_cDataMsg, distance); // tx power
#endif
	if (bStat == true)
	{
		if (eCHSensor == target.GetNodeType())
		{
			gStat.dPACKETTOCH++;
		}
		if (eNodeSink == target.GetNodeType())
		{
			gStat.dPACKETTOBS++;
		}
		cout << "Node# " << GetID() << " sending "
				<< m_cDataMsg.GetMessageLeninBits() << " bits to Node# "
				<< target.GetID() << endl;

		target.Recv(m_cDataMsg); //rx power dec
		target.AppendDataBuffer(m_cDataMsg.GetMessageLeninBits());
	}
	return bStat;
}

bool Node::SendCHtoCH(Message& msg, double distance)
{
	m_dResidualPower = m_dResidualPower
			- TxPowerCalcCHtoCH(distance, msg.GetMessageLeninBits());
	UpdateNodeStatus();
	return Channel::WriteMessageToChannel(msg);
}

bool Node::Send(Message& msg, double distance)
{
	double dResidualPowerReqd = TxPowerCalc(distance,
			msg.GetMessageLeninBits());
	if (dResidualPowerReqd > m_dResidualPower)
	{
		m_bIsActive = false;
	}
	else
	{
		m_dResidualPower = m_dResidualPower - dResidualPowerReqd;
	}
	UpdateNodeStatus();
	return Channel::WriteMessageToChannel(msg);
}

bool Node::IsBetterCH()
{
	bool bStat = false;
	if (eCHSelection == m_cCurMsg.GetMessageType())
	{

		if (m_cCurMsg.GetResidualPower()
				< (m_dResidualPower - dPowerForLEACHAD))
		{
			bStat = true;
		}
		else if ((m_cCurMsg.GetResidualPower()
				== (m_dResidualPower - dPowerForLEACHAD))
				&& m_cCurMsg.GetWinCount() > m_nCHSelectionWinner)
		{
			bStat = true;
		}
	}
	return bStat;

}

Node::~Node()
{
}

ostream & operator<<(ostream &out, Node& n)
{
	out << "Node ID: " << n.GetID() << " X: " << (n.GetPos()).GetXPos()
			<< " Y: " << (n.GetPos()).GetYPos() << " Residual Power "
			<< n.GetResidualPower() << endl;
	return out;
}

